package com.mustafaiev.tair.cts.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.mustafaiev.tair.constant.Attributes;
import com.mustafaiev.tair.constant.PayerRole;
import com.mustafaiev.tair.constant.ViewNames;
import com.mustafaiev.tair.cts.dto.GroupDTO;
import com.mustafaiev.tair.cts.dto.PayerDTO;
import com.mustafaiev.tair.cts.enums.EntityState;
import com.mustafaiev.tair.cts.exeption.DataNotRetrievedException;
import com.mustafaiev.tair.cts.service.GroupService;
import com.mustafaiev.tair.cts.service.PayerService;
import com.mustafaiev.tair.cts.validation.GroupValidator;
import com.mustafaiev.tair.cts.validation.PayerValidator;

@Controller
public class RegistrationController {

	private static final Logger LOGGER = Logger
			.getLogger(RegistrationController.class);

	@Autowired
	private PayerService payerService;

	@Autowired
	private GroupService groupService;

	@InitBinder(value = { "payer" })
	protected void payersInitBinder(final WebDataBinder binder) {
		binder.setValidator(new PayerValidator(this.payerService));
	}

	@InitBinder(value = { "group" })
	protected void groupInitBinder(final WebDataBinder binder) {
		binder.setValidator(new GroupValidator(this.groupService));
	}

	@RequestMapping(value = "/registration", method = RequestMethod.GET)
	public ModelAndView goRegistration(
			@ModelAttribute("payer") final PayerDTO payerDto) {
		final ModelAndView view = new ModelAndView(ViewNames.REGISTRATION);
		return view;
	}

	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public ModelAndView doRegisterUser(
			@Valid @ModelAttribute("payer") final PayerDTO payerDto,
			final BindingResult binder, final HttpServletRequest request) {

		ModelAndView view = null;
		if (binder.hasErrors()) {
			LOGGER.info("Registration was not successful due validation errors");
			view = new ModelAndView(ViewNames.REGISTRATION);
			view.addObject(Attributes.PAYER, payerDto);
		} else {
			payerDto.setRole(PayerRole.ROLE_CTS_GROUP_OWNER);
			payerDto.setState(EntityState.STATE_DRAFT);
			this.payerService.registerPayer(payerDto);
			view = new ModelAndView("redirect:/newGroup");
			request.getSession().setAttribute(Attributes.PAYER_EMAIL,
					payerDto.getEmail());
			LOGGER.info("Payer Registered");
		}
		return view;
	}

	@RequestMapping(value = "/newGroup", method = { RequestMethod.GET })
	public ModelAndView newGroupRegistration(final HttpServletRequest request) {
		final ModelAndView view = new ModelAndView(ViewNames.GROUP_REGISTRATION);
		return view;
	}

	@RequestMapping(value = "/registerGroup", method = RequestMethod.POST)
	public ModelAndView doRegisterGroup(
			@Valid @ModelAttribute("group") final GroupDTO groupDTO,
			final BindingResult binder, final HttpServletRequest request)
			throws DataNotRetrievedException {

		final HttpSession session = request.getSession();
		final String email = (String) session
				.getAttribute(Attributes.PAYER_EMAIL);
		session.removeAttribute(Attributes.PAYER_EMAIL);
		final PayerDTO dto = this.payerService.retrieveByEmail(email);
		dto.setState(EntityState.STATE_ACTIVE);
		ModelAndView view = new ModelAndView("redirect:/");
		if (binder.hasErrors()) {
			view = new ModelAndView(ViewNames.GROUP_REGISTRATION);
			view.addObject(Attributes.GROUP, groupDTO);
		} else {
			groupDTO.setState(EntityState.STATE_ACTIVE);
			groupDTO.setPayer(dto.getId());
			this.groupService.registerGroup(groupDTO);
			this.payerService.updatePayer(dto);
		}
		return view;
	}
}
